<template>
<!-- 文章详情总页面 -->
   <div class="article-container">
      <!-- 导航栏 -->
      <van-nav-bar
         class="page-nav-bar"
         left-arrow
         title="黑马头条"
         @click-left="$router.back()"
      ></van-nav-bar>
      <!-- /导航栏 -->

      <div class="main-wrap">
         <!-- 加载中 -->
         <!-- 加载中显示loading ，加载成功显示内容关闭loading 
         没有内容或删除显示404
         其他错误 网络服务器之类的显示另一种错误
         -->
         <div class="loading-wrap" v-if="loading">
            <van-loading color="#3296fa" vertical
               >加载中</van-loading
            >
         </div>
         <!-- /加载中 -->

         <!-- 加载完成-文章详情 -->
         <div
            class="article-detail"
            v-else-if="article.title"
         >
            <!-- 文章标题 -->
            <h1 class="article-title">
               {{ article.title }}
            </h1>
            <!-- /文章标题 -->

            <!-- 用户信息 -->
            <van-cell
               class="user-info"
               center
               :border="false"
            >
               <!-- 作者头像 -->
               <van-image
                  class="avatar"
                  slot="icon"
                  round
                  fit="cover"
                  :src="article.aut_photo"
               />
               <div slot="title" class="user-name">
                  {{ article.aut_name }}
               </div>
               <div slot="label" class="publish-date">
                  {{ article.pubdate | relativeTime }}
               </div>
               <!-- 模板中的 $event 是事件参数 -->

               <!-- 当我们传递给子组件数据 既要使用还要修改
               传递：props
               :is-followed="article.is_followed"
               修改：自定义事件
               @update-is_followed="
                     article.is_followed = $event"
               简写：在组件上使用 v-model -->

               <!-- v-model 等于：
               传递一个 value="article.is_followed"
               @input="article.is_followed = $event" -->

               <!-- 如果需要修改 v-model 的规则名称，可以通过子组件的
               model 属性配合修改 -->

               <!-- 如果有多个数据要实现 v-model 的效果，v-model只能用一次
               可以去使用 .sync 在 vue.js 去了解 -->
               <!-- 1.一般来说表单相关的自定义组件，
               如果需要内部修改传递的props数据，我们会使用v-model  -->

               <!-- 2. .sync一般是使用在非表单组件上，需要内部修改props数据的地方；
               默认触发事件的名称是 update:xxx，xxx是传递的props属性名  -->

               <!-- <FollowUser
                  :is-followed.sync="article.is_followed"
                  class="follow-btn"
                  :user-id="article.aut_id"
               ></FollowUser> -->
               <FollowUser
                  v-model="article.is_followed"
                  class="follow-btn"
                  :user-id="article.aut_id"
               ></FollowUser>
               <!-- <van-button
                  v-if="article.is_followed"
                  class="follow-btn"
                  round
                  size="small"
                  :loading="followLoading"
                  @click="onFollow"
                  >已关注</van-button
               >
               <van-button
                  v-else
                  class="follow-btn"
                  type="info"
                  color="#3296fa"
                  round
                  size="small"
                  icon="plus"
                  :loading="followLoading"
                  @click="onFollow"
                  >关注</van-button
               > -->
            </van-cell>
            <!-- /用户信息 -->

            <!-- 文章内容 -->
            <div
               class="article-content markdown-body"
               v-html="article.content"
               ref="article_content"
            ></div>
            <van-divider>正文结束</van-divider>
            <!-- 文章评论列表 -->
            <CommentList
               :source="article.art_id"
               :list="commentList"
               @reply-click="onReplyClick"
               @onload-success="
                  totalComment = $event.total_count
               "
            ></CommentList>
            <!-- 底部区域 -->
            <div class="article-bottom">
               <van-button
                  class="comment-btn"
                  type="default"
                  round
                  size="small"
                  @click="isPostShow = true"
                  >写评论</van-button
               >
               <van-icon
                  name="comment-o"
                  :info="totalComment"
                  color="#777"
               />
               <!-- article.art_id  是文章 id -->
               <!-- article.aut_id 是用户 id -->
               <CollectArticle
                  v-model="article.is_collected"
                  :article-id="article.art_id"
               ></CollectArticle>
               <LikeArticle
                  v-model="article.attitude"
                  :article-id="article.art_id"
               ></LikeArticle>
               <!-- <van-icon color="#777" name="star-o" /> -->
               <!-- <van-icon color="#777" name="good-job-o" /> -->
               <van-icon
                  name="share"
                  color="#777777"
               ></van-icon>
            </div>
            <!-- /底部区域 -->
            <!-- 发布评论 -->
            <van-popup
               v-model="isPostShow"
               position="bottom"
            >
               <CommentPost
                  :target="article.art_id"
                  @post-success="onPostSuccess"
               ></CommentPost>
            </van-popup>
         </div>
         <!-- /加载完成-文章详情 -->

         <!-- 加载失败：404 -->
         <div
            class="error-wrap"
            v-else-if="errStatus === 404"
         >
            <van-icon name="failure" />
            <p class="text">该资源不存在或已删除！</p>
         </div>
         <!-- /加载失败：404 -->

         <!-- 加载失败：其它未知错误（例如网络原因或服务端异常） -->
         <div class="error-wrap" v-else>
            <van-icon name="failure" />
            <p class="text">内容加载失败！</p>
            <van-button
               class="retry-btn"
               @click="loadArticle"
               >点击重试</van-button
            >
         </div>
         <!-- /加载失败：其它未知错误（例如网络原因或服务端异常） -->
      </div>
      <!-- 评论回复 -->
      <van-popup
         v-model="isReplyShow"
         position="bottom"
         style="height: 100%;"
      >
         <!-- 弹出层是懒渲染的，只有第一次展示的时候才会渲染里边的内容，
      之后它的关闭和显示都是在切换内容的显示与隐藏 
      list 里边的生命周期 created 只执行了一次，保存到那了，所以没有销毁
      点击另一个回复时再把它展示出来，而不是把它再次调用
      我们需要点关闭时把弹层里的内容销毁，点击另一个在加载新内容
      这样 created 再次执行获取新的数据
      弹层展示的时候把内容重新渲染出来
      随着弹层的关闭销毁内容，随着弹层开启再重新创建加载内容
      v-if 条件渲染
         true: 渲染元素节点
         false :不会渲染
      -->
         <CommentReply
            v-if="isReplyShow"
            :comment="currentComment"
            @close="isReplyShow = false"
         ></CommentReply>
      </van-popup>
   </div>
</template>

<script>
import { getArticleById } from '@/api/article'
import { ImagePreview } from 'vant'
import FollowUser from '../../components/follow-user'
import CollectArticle from '../../components/collect-article'
import LikeArticle from '../../components/like-article'
import CommentList from './components/coment-list.vue'
import CommentPost from './components/comment-post.vue'
import CommentReply from './components/comment-reply.vue'
// import { addFollow, deleteFollow } from '../../api/user'
export default {
   name: 'ArticleIndex',
   components: {
      FollowUser,
      CollectArticle,
      LikeArticle,
      CommentList,
      CommentPost,
      CommentReply
   },
   props: {
      articleId: {
         // 返回的是一个 BigNumber 对象，所以再加一项
         type: [Number, String, Object],
         required: true
      }
   },
   // 依赖注入：跨组件传值
   // 给所有的后代组件提供数据,不用一级一级往下传了
   // 后代组件声明接收 ： inject: ['getMap']  都可以拿到传递的数据
   provide: function() {
      return {
         articleId: this.articleId
      }
   },
   data() {
      return {
         // 文章详情
         article: {},
         // 加载中的 loading 状态
         loading: true,
         // 失败的状态码
         errStatus: 0,
         followLoading: false,
         // 评论数量
         totalComment: 0,
         // 评论回复弹出层状态
         isPostShow: false,
         // 评论列表
         commentList: [],
         // 回复评论的弹出层
         isReplyShow: false,
         // 当前点击回复的评论项
         currentComment: []
      }
   },
   computed: {},
   watch: {},
   created() {
      this.loadArticle()
   },
   mounted() {},
   methods: {
      async loadArticle() {
         this.loading = true
         try {
            // 对象跟字符串拼接 默认 执行对象的 .toString 转成 字符串
            const { data } = await getArticleById(
               this.articleId
            )
            // 模拟报错  不是 404 的报错 另一种失败提示
            // if (Math.random() > 0.5) {
            //    JSON.parse('dsdgddgfdgdgf')
            // }
            // console.log(data)
            this.article = data.data
            // 请求成功，关闭loading
            // this.loading = false

            // 初始化图片点击预览
            // 数据驱动视图这件事不是立即的
            // setTimeout是宏任务 可以放在前
            // DOM 更新是 微任务   先执行微任务 在 执行宏任务
            // this.$nextTick 要放在 数据 更新后
            // this.loading = false 之后
            setTimeout(() => {
               this.previewImages()
            }, 0)
         } catch (err) {
            // response 就是接口报错的 404 的固定结果
            if (
               err.response &&
               err.response.status === 404
            ) {
               this.errStatus = 404
            }
            // this.loading = false
            console.log('获取数据失败', err)
         }
         // 不管成功还是失败都需要关闭 loading
         this.loading = false
      },
      previewImages() {
         // 获取元素
         const articleContent = this.$refs.article_content

         // 获取 图片节点
         const imgs = articleContent.querySelectorAll('img')
         // console.log(imgs)
         // 获取所有 img 地址
         const images = []
         imgs.forEach((img, index) => {
            images.push(img.src)
            // 给每个 img 注册点击事件
            img.onclick = () => {
               ImagePreview({
                  // 预览的图片地址数组
                  images: images,
                  // 起始位置 从0开始
                  startPosition: index

                  // 数据变了 同步
                  // 页面还没变 异步的
                  // 数据的修改是同步的
                  // 页面的渲染是异步的
                  // 1.data数据变化了，Vue是在nextTick中更新DOM的，所以是异步的

                  // 2.this.$nextTick其实就是调用了Vue源码内部的nextTick函数，
                  //       它与数据更新造成的异步DOM更新的nextTick是一致的，都是微任务，
                  //       如果要使用 this.$nextTick 需要放在DOM更新之后

                  // 3.nextTick其实就是判断当前环境，选择一种异步操作,
                  //    Promise > MutationObserver > setImmediate > setTimeout
               })
            }
         })
      },
      onPostSuccess(data) {
         // 关闭弹出层
         this.isPostShow = false
         // 将发布内容显示列表顶部
         this.commentList.unshift(data.new_obj)
      },
      onReplyClick(comment) {
         // console.log(comment)
         this.currentComment = comment
         this.isReplyShow = true
      }
      // async onFollow() {
      //    // 展示关注按钮的 loading 状态
      //    this.followLoading = true
      //    try {
      //       if (this.article.is_followed) {
      //          // 已关注，取消关注
      //          await deleteFollow(this.article.aut_id)
      //          // console.log(data)
      //          // this.article.is_followed = false
      //       } else {
      //          // 未关注，添加关注
      //          await addFollow(this.article.aut_id)
      //          // console.log(data)
      //          // this.article.is_followed = true
      //       }
      //       // 更新视图状态
      //       this.article.is_followed = !this.article
      //          .is_followed
      //    } catch (err) {
      //       let message = '操作失败，请重试'
      //       if (
      //          err.response &&
      //          err.response.status === 400
      //       ) {
      //          message = '你不能关注你自己'
      //       }
      //       this.$toast(message)
      //    }
      //    // 关闭关注按钮的 loading 状态
      //    this.followLoading = false
      // }
   }
}
</script>

<style scoped lang="less">
@import './github-markdown.css';
.article-container {
   .main-wrap {
      position: fixed;
      left: 0;
      right: 0;
      top: 92px;
      bottom: 88px;
      overflow-y: scroll;
      background-color: #fff;
   }
   .article-detail {
      .article-title {
         font-size: 40px;
         padding: 50px 32px;
         margin: 0;
         color: #3a3a3a;
      }

      .user-info {
         padding: 0 32px;
         .avatar {
            width: 70px;
            height: 70px;
            margin-right: 17px;
         }
         .van-cell__label {
            margin-top: 0;
         }
         .user-name {
            font-size: 24px;
            color: #3a3a3a;
         }
         .publish-date {
            font-size: 23px;
            color: #b7b7b7;
         }
         .follow-btn {
            width: 170px;
            height: 58px;
         }
      }

      .article-content {
         padding: 55px 32px;
         /deep/ p {
            text-align: justify;
         }
      }
   }

   .loading-wrap {
      padding: 200px 32px;
      display: flex;
      align-items: center;
      justify-content: center;
      background-color: #fff;
   }

   .error-wrap {
      padding: 200px 32px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      background-color: #fff;
      .van-icon {
         font-size: 122px;
         color: #b4b4b4;
      }
      .text {
         font-size: 30px;
         color: #666666;
         margin: 33px 0 46px;
      }
      .retry-btn {
         width: 280px;
         height: 70px;
         line-height: 70px;
         border: 1px solid #c3c3c3;
         font-size: 30px;
         color: #666666;
      }
   }

   .article-bottom {
      position: fixed;
      left: 0;
      right: 0;
      bottom: 0;
      display: flex;
      justify-content: space-around;
      align-items: center;
      box-sizing: border-box;
      height: 88px;
      border-top: 1px solid #d8d8d8;
      background-color: #fff;
      .comment-btn {
         width: 282px;
         height: 46px;
         border: 2px solid #eeeeee;
         font-size: 30px;
         line-height: 46px;
         color: #a7a7a7;
      }
      /deep/ .van-icon {
         font-size: 40px;
         .van-info {
            font-size: 16px;
            background-color: #e22829;
         }
      }
   }
}
</style>
